﻿using System;
using System.Data.SqlClient;
using System.Linq;
using System.Threading;
using Common.Logging;
using Newtonsoft.Json;
using OutDbContext;
using Rmq.Center;
using User.Api.BizExtensions;
using User.Api.Helpers;
using User.Api.Helpers.WeixinPayV3.WxResult;

namespace Out.TaskRunner.RmqWorkers
{
    public class OrderRefundingUnpickupSucceedWorker : IWorker
    {
        private static readonly ILog Logger = LogManager.GetLogger(typeof(OrderRefundingUnpickupSucceedWorker));

        public void Start(CancellationToken ct)
        {
            if (ct.IsCancellationRequested)
            {
                return;
            }

            using (var consumer = new OrderRefundingUnpickupSucceedConsumer())
            {
                consumer.Subscribe((id, count, dt, msg, channel) =>
                {
                    if (msg.OrderType == OrderType.挂号订单)
                    {
                        return ProcessRegOrder(msg.OrderId, channel,msg.Reason);
                    }
                    else if(msg.OrderType == OrderType.扫码支付订单)
                    {
                        return ProcessSCOrder(msg.OrderId, channel, msg.Reason);
                    }

                    return new ConsumedResult { Ack = true };
                });

                while (true)
                {
                    if (ct.IsCancellationRequested)
                    {
                        break;
                    }

                    Thread.Sleep(500);
                }
            }
        }

        private ConsumedResult ProcessRegOrder(int orderId, WrapperChannel channel, int reason)
        {
            OrderSummary order;
            string openId;
            using (var ctx = new HzfyWeiXinEntities())
            {
                order = ctx.ApptOrder.Where(x => x.Id == orderId).
                    Select(x => new OrderSummary()
                    {
                        OrderStatus = x.OrderStatus,
                        PayState = x.PayState,
                        Id = x.Id,
                        WxTransactionId = x.WxTransactionId,
                        OrderNo = x.OrderNo,
                        WxUserId = x.WxUserId,
                        SumFee = x.SumFee
                    }).FirstOrDefault();
                if (order == null)
                {
                    return new ConsumedResult
                    {
                        Ack = true
                    };
                }
                openId = ctx.WxUser.Where(x => x.Id == order.WxUserId).Select(x => x.OpenId).FirstOrDefault();
                // 微信退号退款中
                //order.OrderStatus = ApptOrderExtensions.OrderStatus.微信退号退款中.ToInt32();
                //order.PayState = ApptOrderExtensions.PayState.退款中.ToInt32().ToString();
                //order.RefundReason = reason == 4 ? "窗口退号" : "因退号而退款";
                //ctx.SaveChanges();

                SqlParameter[] para =
                {
                    new SqlParameter("@OrderStatus", ApptOrderExtensions.OrderStatus.微信退号退款中.ToInt32()),
                    new SqlParameter("@PayState", ApptOrderExtensions.PayState.退款中.ToInt32().ToString()),
                    new SqlParameter("@RefundReason", "因退号而退款"),
                    new SqlParameter("@OrderId", order.Id)
                };
                ctx.Database.ExecuteSqlCommand(
                    "Update ApptOrder set OrderStatus= @OrderStatus,PayState = @PayState,RefundReason=@RefundReason where Id=@OrderId",
                    para);

            }

            DoRefundResult refundResult = new DoRefundResult();
            try
            {
                refundResult = WeixinPayV3Helper.DoRefund("AP" + order.OrderNo, order.WxTransactionId,
                    "AP" + order.OrderNo, (order.SumFee*100).ToInt32(), (order.SumFee*100).ToInt32());

            }
            catch (Exception ex)
            {
                Logger.ErrorFormat("调用第三方支付退款Api出错,信息：{0}", JsonConvert.SerializeObject(ex));
                return new ConsumedResult
                {
                    Ack = false,
                    Delay = 1000
                };
            }
            //退款成功 4,10
            //退款处理中 8 9 11
            if (refundResult.RefundStatus == 4 || refundResult.RefundStatus == 10 ||
                refundResult.RefundStatus == 8 || refundResult.RefundStatus == 9 || refundResult.RefundStatus == 11)
            {
                // 微信退号退款成功
                //order.OrderStatus = ApptOrderExtensions.OrderStatus.微信退号退款成功.ToInt32();
                //order.RefundReason = "因退号而退款";
                //order.PayState = ApptOrderExtensions.PayState.已退款.ToInt32().ToString();
                //order.RefundTime = DateTime.Now;
                //order.WxRefundId = refundResult.RefundId;
                //ctx.SaveChanges();
                using (var ctx = new HzfyWeiXinEntities())
                {
                    SqlParameter[] para = new SqlParameter[]
                    {
                        new SqlParameter("@OrderStatus", ApptOrderExtensions.OrderStatus.微信退号退款成功.ToInt32()),
                        new SqlParameter("@PayState", ApptOrderExtensions.PayState.已退款.ToInt32().ToString()),
                        new SqlParameter("@RefundReason", "因退号而退款"),
                        new SqlParameter("@RefundTime", DateTime.Now),
                        new SqlParameter("@WxRefundId", refundResult.RefundId),
                        new SqlParameter("@OrderId", order.Id)
                    };
                    ctx.Database.ExecuteSqlCommand(
                        "Update ApptOrder set OrderStatus= @OrderStatus,PayState = @PayState,RefundReason=@RefundReason, " +
                        "RefundTime = @RefundTime,WxRefundId = @WxRefundId where Id=@OrderId", para);
                }

                // RMQ 发送用户退费成功通知

                var msgProducer = new UserMessageProducer();
                msgProducer.Publish(new UserMessageMsg
                {
                    Type = reason == 3 ? UserMessageType.停诊退号成功通知 : UserMessageType.退号成功退费成功通知,
                    OrderId = order.Id
                });

                //TenpayV2Helper.DoDeliverNotify(wxuser.OpenId, order.WxTransactionId,
                //    "AP" + order.OrderNo, "0", "RefundSucceed");
                if (!string.IsNullOrEmpty(openId))
                {
                    WeixinPayV3Helper.DoDeliveryNotify(openId, order.WxTransactionId,
                        "AP" + order.OrderNo, ((DateTime.Now.ToUniversalTime().Ticks - 621355968000000000)/10000000)
                            .ToString(), "0", "RefundSucceed");
                }
                return new ConsumedResult
                {
                    Ack = true
                };
            }
            //退款失败 3，5，6
            //转入代发 7
            if (refundResult.RefundStatus == 7 ||
                refundResult.RefundStatus == 3 || refundResult.RefundStatus == 5 || refundResult.RefundStatus == 6)
            {
                // 微信退号退款失败
                //order.OrderStatus = ApptOrderExtensions.OrderStatus.微信退号退款失败.ToInt32();
                //order.PayState = ApptOrderExtensions.PayState.退款失败.ToInt32().ToString();
                //ctx.SaveChanges();
                using (var ctx = new HzfyWeiXinEntities())
                {
                    SqlParameter[] para = new SqlParameter[]
                    {
                        new SqlParameter("@OrderStatus", ApptOrderExtensions.OrderStatus.微信退号退款失败.ToInt32()),
                        new SqlParameter("@PayState", ApptOrderExtensions.PayState.退款失败.ToInt32().ToString()),
                        new SqlParameter("@OrderId", order.Id)
                    };
                    ctx.Database.ExecuteSqlCommand(
                        "Update ApptOrder set OrderStatus= @OrderStatus,PayState = @PayState where Id=@OrderId",
                        para);

                }
                //TenpayV2Helper.DoDeliverNotify(wxuser.OpenId, order.WxTransactionId,
                //    "AP" + order.OrderNo, "0", "RefundFailed");
                if (!string.IsNullOrEmpty(openId))
                {
                    WeixinPayV3Helper.DoDeliveryNotify(openId, order.WxTransactionId,
                        "AP" + order.OrderNo, ((DateTime.Now.ToUniversalTime().Ticks - 621355968000000000)/10000000)
                            .ToString(), "0", "RefundFailed");
                }
                return new ConsumedResult
                {
                    Ack = true
                };
            }

            // 1，2：未确定，需要商户原退款单号重新发起
            if (refundResult.RefundStatus == 1 || refundResult.RefundStatus == 2)
            {
                return new ConsumedResult
                {
                    Ack = false,
                    Delay = 1000
                };
            }


            return new ConsumedResult
            {
                Ack = true
            };
        }

        private ConsumedResult ProcessSCOrder(int orderId, WrapperChannel channel, int reason)
        {
            OrderSummary order;
            string openId;
            using (var ctx = new HzfyWeiXinEntities())
            {
                order = ctx.BillOrder.Where(x => x.Id == orderId).
                    Select(x => new OrderSummary()
                    {
                        OrderStatus = x.OrderStatus,
                        PayState = x.PayState,
                        Id = x.Id,
                        WxTransactionId = x.WxTransactionId,
                        OrderNo = x.OrderNo,
                        //WxUserId = x.WxUserId,
                        SumFee = x.PrescMoney
                    }).FirstOrDefault();
                if (order == null)
                {
                    return new ConsumedResult
                    {
                        Ack = true
                    };
                }
                //openId = ctx.WxUser.Where(x => x.Id == order.WxUserId).Select(x => x.OpenId).FirstOrDefault();

                SqlParameter[] para =
                {
                    new SqlParameter("@OrderStatus", BillOrderExtensions.OrderStatus.退款中.ToInt32()),
                    new SqlParameter("@PayState", BillOrderExtensions.PayState.退款中.ToInt32().ToString()),
                    new SqlParameter("@OrderId", order.Id)
                };
                ctx.Database.ExecuteSqlCommand(
                    "Update BillOrder set OrderStatus= @OrderStatus,PayState = @PayState where Id=@OrderId",
                    para);

            }

            DoRefundResult refundResult = new DoRefundResult();
            try
            {
                refundResult = WeixinPayV3Helper.DoRefund("SC" + order.OrderNo, order.WxTransactionId,
                    "SC" + order.OrderNo, (order.SumFee * 100).ToInt32(), (order.SumFee * 100).ToInt32());

            }
            catch (Exception ex)
            {
                Logger.ErrorFormat("调用第三方支付退款Api出错,信息：{0}", JsonConvert.SerializeObject(ex));
                return new ConsumedResult
                {
                    Ack = false,
                    Delay = 1000
                };
            }
            Logger.ErrorFormat("调用第三方支付退款Api出错,信息：{0}", refundResult.RefundStatus);

            //退款成功 4,10
            //退款处理中 8 9 11
            if (refundResult.RefundStatus == 4 || refundResult.RefundStatus == 10 ||
                refundResult.RefundStatus == 8 || refundResult.RefundStatus == 9 || refundResult.RefundStatus == 11)
            {
                using (var ctx = new HzfyWeiXinEntities())
                {
                    SqlParameter[] para = new SqlParameter[]
                    {
                        new SqlParameter("@OrderStatus", BillOrderExtensions.OrderStatus.窗口退款成功.ToInt32()),
                        new SqlParameter("@PayState", BillOrderExtensions.PayState.已退款.ToInt32().ToString()),
                        new SqlParameter("@Remark", "自助机退费"),
                        new SqlParameter("@RefundTime", DateTime.Now),
                        new SqlParameter("@WxRefundId", refundResult.RefundId),
                        new SqlParameter("@OrderId", order.Id)
                    };
                    ctx.Database.ExecuteSqlCommand(
                        "Update BillOrder set OrderStatus= @OrderStatus,PayState = @PayState,Remark=@Remark, " +
                        "RefundTime = @RefundTime,WxRefundId = @WxRefundId where Id=@OrderId", para);
                }

                // RMQ 发送用户退费成功通知

                //var msgProducer = new UserMessageProducer();
                //msgProducer.Publish(new UserMessageMsg
                //{
                //    Type = reason == 3 ? UserMessageType.停诊退号成功通知 : UserMessageType.退号成功退费成功通知,
                //    OrderId = order.Id
                //});

                //TenpayV2Helper.DoDeliverNotify(wxuser.OpenId, order.WxTransactionId,
                //    "AP" + order.OrderNo, "0", "RefundSucceed");
                //if (!string.IsNullOrEmpty(openId))
                //{
                //    WeixinPayV3Helper.DoDeliveryNotify(openId, order.WxTransactionId,
                //        "AP" + order.OrderNo, ((DateTime.Now.ToUniversalTime().Ticks - 621355968000000000) / 10000000)
                //            .ToString(), "0", "RefundSucceed");
                //}
                return new ConsumedResult
                {
                    Ack = true
                };
            }
            //退款失败 3，5，6
            //转入代发 7
            if (refundResult.RefundStatus == 7 ||
                refundResult.RefundStatus == 3 || refundResult.RefundStatus == 5 || refundResult.RefundStatus == 6)
            {
                // 微信退号退款失败
                //order.OrderStatus = ApptOrderExtensions.OrderStatus.微信退号退款失败.ToInt32();
                //order.PayState = ApptOrderExtensions.PayState.退款失败.ToInt32().ToString();
                //ctx.SaveChanges();
                using (var ctx = new HzfyWeiXinEntities())
                {
                    SqlParameter[] para = new SqlParameter[]
                    {
                        new SqlParameter("@OrderStatus", BillOrderExtensions.OrderStatus.退款失败.ToInt32()),
                        new SqlParameter("@PayState", BillOrderExtensions.PayState.退款失败.ToInt32().ToString()),
                        new SqlParameter("@Remark", refundResult.ResultMsg),
                        new SqlParameter("@OrderId", order.Id)
                    };
                    ctx.Database.ExecuteSqlCommand(
                        "Update BillOrder set OrderStatus= @OrderStatus,Remark=@Remark,PayState = @PayState where Id=@OrderId",
                        para);

                }
                //TenpayV2Helper.DoDeliverNotify(wxuser.OpenId, order.WxTransactionId,
                //    "AP" + order.OrderNo, "0", "RefundFailed");
                //if (!string.IsNullOrEmpty(openId))
                //{
                //    WeixinPayV3Helper.DoDeliveryNotify(openId, order.WxTransactionId,
                //        "AP" + order.OrderNo, ((DateTime.Now.ToUniversalTime().Ticks - 621355968000000000) / 10000000)
                //            .ToString(), "0", "RefundFailed");
                //}
                return new ConsumedResult
                {
                    Ack = true
                };
            }

            // 1，2：未确定，需要商户原退款单号重新发起
            if (refundResult.RefundStatus == 1 || refundResult.RefundStatus == 2)
            {
                return new ConsumedResult
                {
                    Ack = false,
                    Delay = 1000
                };
            }


            return new ConsumedResult
            {
                Ack = true
            };
        }

        public class OrderSummary
        {
            public int OrderStatus { get; set; }
            public string PayState { get; set; }
            public int Id { get; set; }
            public string WxTransactionId { get; set; }
            public long? WxUserId { get; set; }
            public string OrderNo { get; set; }
            public decimal? SumFee { get; set; }
        }

    }
}